﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Security.Permissions;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;

using Swaf;
using Swaf.BizObj;
using Swaf.Gui;
namespace ScsAspNetMsChart
{
	[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
	[Themeable(true)]
	[ParseChildren(true, "Series")]
	public class MsChartBizObjListDisplay : UserControl, IBizObjListDisplay, IBizObjDisplay
	{
		protected string m_parentBizProcs;
		protected IBizObj m_curBizObj = null;
		protected IBizObjList m_bizObjs = null;

		protected Chart m_chart;
		protected int m_inclination = 30;
		protected bool m_enable3d = false;
		protected bool m_semiTransparent = false;
		protected bool m_showLegend = false;
		protected ChartType m_type = ChartType.Bar;
		protected List<ChartSeries> m_series = new List<ChartSeries>();

		System.Web.UI.WebControls.Unit m_width, m_height;


		[Category("Appearance")]
		public int Inclination { get { return m_inclination; } set { m_inclination = value; } }

		[Category("Appearance")]
		public bool Enable3d { get { return m_enable3d; } set { m_enable3d = value; } }

		[Category("Appearance")]
		public bool SemiTransparent { get { return m_semiTransparent; } set { m_semiTransparent = value; } }

		[Category("Appearance")]
		public bool ShowLegend { get { return m_showLegend; } set { m_showLegend = value; } }

		[Category("Appearance")]
		public ChartType DisplayType { get { return m_type; } set { m_type = value; } }

		[Category("Appearance")]
		public System.Web.UI.WebControls.Unit Width { get { return m_width; } set { m_width = value; } }

		[Category("Appearance")]
		public System.Web.UI.WebControls.Unit Height { get { return m_height; } set { m_height = value; } }

		public List<ChartSeries> Series { get { return m_series; } }

		protected internal Chart ChartDisp
		{
			get
			{
				if (m_chart == null)
					m_chart = new Chart();
				return m_chart;
			}
		}

		protected override void Render(HtmlTextWriter writer)
		{
			ChartDisp.RenderType = RenderType.ImageTag;
			//m_chart.Palette = ChartColorPalette.SeaGreen;
			m_chart.ChartAreas.Add("Default");
			if (Enable3d)
			{
				m_chart.ChartAreas["Default"].Area3DStyle.Enable3D = true;
				m_chart.ChartAreas["Default"].Area3DStyle.Inclination = Inclination;
			}

			if (m_curBizObj != null)
				foreach (ChartSeries s in Series)
					s.setupChart(this, m_curBizObj);
			else if (m_bizObjs != null)
				foreach (ChartSeries s in Series)
					s.setupChart(this, m_bizObjs);


			m_chart.Width = Width;
			m_chart.Height = Height;
			m_chart.Page = Page;

			if (SemiTransparent)
			{
				m_chart.ApplyPaletteColors();
				foreach(Series se in m_chart.Series)
					foreach (DataPoint p in se.Points)
					p.Color = System.Drawing.Color.FromArgb(127, p.Color);
			}
			if (ShowLegend)
				m_chart.Legends.Add("Legend1").Enabled = true;

			m_chart.RenderControl(writer);
		}

		#region IBizObjListDisplay Members

		public void showBizObjs(IBusinessProcess bizProc, Swaf.BizObj.IBizObjCursor list)
		{
			m_bizObjs = list.Source;
		}

		public Swaf.BizObj.IBizObj SelectedBizObj
		{
			get
			{
				return null;
			}
			set
			{
				//Intentionally left blank, this is a read only control.
			}
		}

		public object SelectedBizObjKeyValue
		{
			get
			{
				return null;
			}
			set
			{
				//Intentionally left blank, this is a read only control.
			}
		}

		public void getSelectedBizObjs(Swaf.BizObj.IBizObjList selected)
		{
			//Intentionally left blank, this is a read only control.
		}

		public void setSelectedBizObjs(Swaf.BizObj.IBizObjList selected)
		{
			//Intentionally left blank, this is a read only control.
		}

		public void updateBizObjs()
		{
			//Intentionally left blank, this is a read only control.
		}

		public void refresh()
		{
			//TODO: Is there really anything to do here??
		}

		public Swaf.Security.Privileges EditPrivilege
		{
			get
			{
				return Swaf.Security.Privileges.ReadOnly;
			}
			set
			{
				//Intentionally left blank, this is a read only control.
			}
		}

		public string MaxElements
		{
			get
			{
				return "";
			}
			set
			{
				//Intentionally left blank, this control always uses all elements its been given.
			}
		}

		public bool DrivenByBizProc
		{
			get
			{
				throw new NotImplementedException();
			}
			set
			{
				throw new NotImplementedException();
			}
		}

		public event BizObjSelectedInfo BizObjSelected;

		public event BizObjChanged BizObjUpdated;

		public event BizObjChanged BizObjDeleted;

		public event BizObjChanged BizObjAdded;

		#endregion

		#region IWidget Members

		public string WidgetId
		{
			get { return ClientID; }
		}

		public string ParentBizProcIds { get { return m_parentBizProcs; } set { m_parentBizProcs = value; } }

		public BizProcWidgetType BizProcWidgetType
		{
			get
			{
				BizProcWidgetType t = BizProcWidgetType.list;
				if (Series.Count > 0)
					t = Series[0].BizProcWidgetType;
				return t;
			}
			set
			{
			}
		}

		#endregion

		#region IBizObjDisplay Members

		public void displayBizObj(IBizObj bizObj)
		{
			m_curBizObj = bizObj;
		}

		public void updateBizObj(IBizObj bizObj)
		{
			//Intentionally left blank, this is a read only control
		}

		public bool isSelected
		{
			get { return false; }
		}

		public bool isDisplayingContent
		{
			get { return m_curBizObj != null; }
		}

		#endregion
	}

	public abstract class ChartSeries
	{
		protected ChartType m_type = ChartType.None;
		protected string m_labelStyle;

		public ChartType DisplayType { get { return m_type; } set { m_type = value; } }
		public string LableStyle { get { return m_labelStyle; } set { m_labelStyle = value; } }

		protected internal virtual void setupChart(MsChartBizObjListDisplay chart, IBizObjList bizObjs)
		{
		}
		protected internal virtual void setupChart(MsChartBizObjListDisplay chart, IBizObj bizObj)
		{
		}

		public abstract BizProcWidgetType BizProcWidgetType { get; }

		protected string calculateText(IBizObj bizObj, string textField, params string[] text)
		{
			string t = "";
			for(int p = 0; p < text.Length; p++)
				if (!Cmn.IsEmpty(text[p]))
				{
					t = text[p];
					break;
				}
			if (!Cmn.IsEmpty(textField) && bizObj != null && bizObj.containsField(textField))
				t = bizObj.get(textField).ToString();
			return t;
		}

		protected SeriesChartType convertChartType(ChartType t1, ChartType t2)
		{
			SeriesChartType ct = SeriesChartType.Bar;
			ChartType t = t1;
			if (t == ChartType.None)
				t = t2;
			switch (t)
			{
				case ChartType.Line:
					ct = SeriesChartType.Line;
					break;
				case ChartType.Pie:
					ct = SeriesChartType.Pie;
					break;
				case ChartType.Column:
					ct = SeriesChartType.Column;
					break;
			}
			return ct;
		}
	}

	public class SeriesElement
	{

		protected string m_text, m_bizObjTextField;
		protected string m_bizObjValueField;

		public string Text { get { return m_text; } set { m_text = value; } }
		public string TextField { get { return m_bizObjTextField; } set { m_bizObjTextField = value; } }
		public string ValueField { get { return m_bizObjValueField; } set { m_bizObjValueField = value; } }
	}

	[ParseChildren(true, "Items")]
	public class FieldSeries : ChartSeries
	{
		protected string m_title, m_titleField;
		protected List<SeriesElement> m_items = new List<SeriesElement>();

		public string Title { get { return m_title; } set { m_title = value; } }
		public string TitleField { get { return m_titleField; } set { m_titleField = value; } }
		public List<SeriesElement> Items { get { return m_items; } }

		protected internal override void setupChart(MsChartBizObjListDisplay chart, IBizObj bizObj)
		{
			Series s = chart.ChartDisp.Series.Add(calculateText(bizObj, TitleField, Title));
			if (!Cmn.IsEmpty(this.LableStyle))
				s["LabelStyle"] = this.LableStyle;
			s.ChartType = convertChartType(DisplayType, chart.DisplayType);
			foreach (SeriesElement se in Items)
				s.Points.AddXY(calculateText(bizObj, se.TextField, se.Text, se.ValueField), bizObj.get(se.ValueField));
			
		}
		public override BizProcWidgetType BizProcWidgetType
		{
			get { return BizProcWidgetType.disp; }
		}
	}
	[ParseChildren(true, "Items")]
	public class ListFieldSeries : FieldSeries
	{
		protected string m_bizObjTextField;

		public string TextField { get { return m_bizObjTextField; } set { m_bizObjTextField = value; } }

		protected internal override void setupChart(MsChartBizObjListDisplay chart, IBizObjList bizObjs)
		{
			bool hasTextField = !Cmn.IsEmpty(TextField);
			List<Series> ss = new List<Series>();
			foreach (SeriesElement se in Items)
			{
				ss.Add(chart.ChartDisp.Series.Add(se.Text));
				if (!Cmn.IsEmpty(this.LableStyle))
					ss[ss.Count-1]["LabelStyle"] = this.LableStyle;
				ss[ss.Count - 1].ChartType = convertChartType(DisplayType, chart.DisplayType);
			}


			int bizObjPos = 0;
			foreach (IBizObj bizObj in bizObjs)
			{
				object xVal = ++bizObjPos;
				if (hasTextField)
					xVal = bizObj.get(TextField);
				for (int p = 0; p < ss.Count; p++)
					ss[p].Points.AddXY(xVal, bizObj.get(Items[p].ValueField));
			}
			
		}
		public override BizProcWidgetType BizProcWidgetType
		{
			get { return BizProcWidgetType.list; }
		}
	}


	[ParseChildren(true)]
	public class CompositChartSeries : ChartSeries
	{
		protected List<ChartSeries> m_items = new List<ChartSeries>();

		public List<ChartSeries> Items { get { return m_items; } }
		public override BizProcWidgetType BizProcWidgetType
		{
			get { return BizProcWidgetType.list; }
		}
	}

	public enum ChartType {None, Line, Pie, Bar, Column };

}
